//
//  NMWebViewController.swift
//  NetEaseMusic
//
//  Created by SAGESSE on 2020/5/29.
//  Copyright © 2020 SAGESSE. All rights reserved.
//

import UIKit
import WebKit


@objc protocol NMWebViewDelegate {
    
    @objc optional func webView(_ webView: NMWebView, titleDidChange title: String?)
    @objc optional func webView(_ webView: NMWebView, progressDidChange progress: Double)
    
}

@IBDesignable class NMWebView: WKWebView {
    
    var enableHandleWkWebViewCookie: Bool = true

    weak var delegate: NMWebViewDelegate?
    
    override init(frame: CGRect, configuration: WKWebViewConfiguration) {
        super.init(frame: frame, configuration: configuration)
        self.setup()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        self.setup()
    }

    override func goBack() -> WKNavigation? {
        return super.goBack().map(trace)
    }
    override func goForward() -> WKNavigation? {
        return super.goForward().map(trace)
    }
    
    override func reload() -> WKNavigation? {
        return super.reload().map(trace)
    }
    

    
    func unsafeEvaluateJavaScript(_ javaScriptString: String, completionHandler: ((Any?, Error?) -> Void)? = nil) {
        DispatchQueue.main.async {
            self.evaluateJavaScript(javaScriptString, completionHandler: completionHandler)
        }
    }
    
    
//    override func load(_ data: Data, mimeType MIMEType: String, characterEncodingName: String, baseURL: URL) -> WKNavigation? {
//        super.load(data, mimeType: MIMEType, characterEncodingName: characterEncodingName, baseURL: baseURL).map(trace)
//    }
//
//    override func loadFileURL(_ URL: URL, allowingReadAccessTo readAccessURL: URL) -> WKNavigation? {
//        super.loadFileURL(URL, allowingReadAccessTo: readAccessURL).map(trace)
//    }

    override func load(_ request: URLRequest) -> WKNavigation? {
        while true {
            guard enableHandleWkWebViewCookie else {
                break
            }
            
            guard let url = request.url, let host = url.host, !host.isEmpty else {
                break
            }
            
            // ???
            // handleAjaxCookieWithUrl:
            inject(url)
            
            guard let cookie = HTTPCookieStorage.shared.cookies(for: url).map(HTTPCookie.requestHeaderFields)?["Cookie"] else {
                break
            }
            
            var newValue = request
            newValue.setValue(cookie, forHTTPHeaderField: "Cookie")
            return super.load(newValue).map(trace)
        }
        return super.load(request).map(trace)
    }
    
    override func loadHTMLString(_ string: String, baseURL: URL?) -> WKNavigation? {
        super.loadHTMLString(string, baseURL: baseURL).map(trace)
    }

    override func didChangeValue(forKey key: String) {
        switch key {
        case "title":
            logger.trace?.write("update title \(title ?? "")")
            delegate?.webView?(self, titleDidChange: title)
            
        case "estimatedProgress":
            logger.trace?.write("update loading progress \(Int(estimatedProgress * 100))%")
            delegate?.webView?(self, progressDidChange: estimatedProgress)
            
            // Ignore when the progress is not change.
            guard displayedProgress != estimatedProgress else {
                return
            }
            displayedProgress = estimatedProgress
            
            // Must copy progress, otherwise the animation will be interrupted.
            let newValue = displayedProgress
            let progressView = displayedProgressView
            
            let animations = {
                // Generate a change animation from left to right.
                progressView.frame.size.width = self.frame.width * .init(newValue)
            }
            
            UIView.animate(withDuration: 0.3, animations: animations) { _ in
                // When progress is equal to 1, automatic hidden the progress view.
                progressView.isHidden = (newValue >= 1)
            }

        default:
            break
        }
        super.didChangeValue(forKey: key)
    }
    
    private func trace(_ nav: WKNavigation) -> WKNavigation {
        // [NEWebViewNavigation navigationFromWKNavigation:navigation]
        return nav
    }
    private func format(_ cookie: HTTPCookie) -> String {
        return ""
    }

    private func inject(_ url: URL) {
        
        guard let cookies = HTTPCookieStorage.shared.cookies(for: url), !cookies.isEmpty else {
            return
        }
        

    }
    private func setup() {
        // Why?
        NotificationCenter.default.addObserver(self, selector: #selector(setNeedsLayout), name: UIApplication.keyboardWillHideNotification, object: nil)
        
        configuration.userContentController.then {
            // Inject bridge.
            //"buildBridgeWithUserContentController:
            
            // Inject wkwebview flags.
            $0.addUserScript(.init(source: "var nejs_is_wkwebview = true;",
                                   injectionTime: .atDocumentStart,
                                   forMainFrameOnly: false))
        }
        
        

        displayedProgressView.frame = .init(x: 0, y: 0, width: 0, height: 2)
        displayedProgressView.backgroundColor = .gray
        
        // ..
        
        addSubview(displayedProgressView)
    }
    

    private var displayedProgress: Double = 0.0
    private var displayedProgressView: UIView = .init()
}

@IBDesignable class NMWebViewController: UIViewController, NMWebViewDelegate {
    
    // orpheus://nm/base/webview
    // https://mp.music.163.com/5d68eb6ce00af3537deb7411
    // https://mp.music.163.com/5d68eb6ce00af3537deb7411
    
    // NEJSBSNavigatorPush
    //  https://music.163.com/prime/m/pendant?from=decoration&pendantId=59203
//    <__NSGlobalBlock__: 0x108314028>
//    signature: "v16@?0@"<NMNavigatorParamProtocol>"8"
//    invoke   : 0x104caa150 (/private/var/containers/Bundle/Application/6000D143-AC0C-4140-818E-0D5CE7ABC1E4/neteasemusic.app/neteasemusic`<unknown invoke symbol>)

    
    //-[NMNavigator navigateWithURLString:paramsMaker:]:
    // 个性装扮 https://mp.music.163.com/5d68eb6ce00af3537deb7411
    
    // 登录保护 https://music.163.com/st/platform/protect
    //         http://platform.music.163.com/platform/protect
    // 智能硬件 https://st.music.163.com/smart-device
    
    // 青少年模式 https://music.163.com/st/platform/young/home?bounces=false&type=0
    // 帮助与反馈 https://music.163.com/st/platform/feedback
    
//    Cookie: appver=7.0.0; buildver=1466; channel=distribution; deviceId=257604cb0034734e122f98722a28fa3c; machineid=iPhone10.1; os=iPhone OS; osver=13.5; JSESSIONID-WYYY=IM2FZS1tzYSwG0NWN%2FqWBJ3K%5C8UG9DR%2BY%2F8VMosxT9qwfKlHHaehk9GQCWlFmNHnVYy%5Cd%5CJtB0OFZ%5CUqcq6py7arJmhZwMMCy%2B%2BeIIXmcEgjWbIpPieO88%2Bs8EEWjIDvqKtTNo2Ju%2FTDZg4qJcPm%5CYO1O5prPdijvPS%5CfnllYasB7yhr%3A1590976920220; _iuqxldmzr_=33; _ntes_nnid=310cc4140d9a636f38c8df33d1e9bd19,1590947870564; _ntes_nuid=310cc4140d9a636f38c8df33d1e9bd19; MUSIC_U=e358cc9187d186b8a53adbbb1bb57faac13d5952a1c847e89e70eeddcb2de41333a649814e309366; __remember_me=true
    
//    appver=7.0.0; buildver=1466; channel=distribution; deviceId=257604cb0034734e122f98722a28fa3c; machineid=iPhone10.1; os=iPhone OS; osver=13.5; JSESSIONID-WYYY=IM2FZS1tzYSwG0NWN%2FqWBJ3K%5C8UG9DR%2BY%2F8VMosxT9qwfKlHHaehk9GQCWlFmNHnVYy%5Cd%5CJtB0OFZ%5CUqcq6py7arJmhZwMMCy%2B%2BeIIXmcEgjWbIpPieO88%2Bs8EEWjIDvqKtTNo2Ju%2FTDZg4qJcPm%5CYO1O5prPdijvPS%5CfnllYasB7yhr%3A1590976920220; _iuqxldmzr_=33; __csrf=d3c2462d9f5acd49b658126d57254620; _ntes_nnid=310cc4140d9a636f38c8df33d1e9bd19,1590947870564; _ntes_nuid=310cc4140d9a636f38c8df33d1e9bd19; WM_NI=raI0QH6kT3BgQWx4mWSLnebmTWIDZ4WdZyKCScS5oaZNEsOKYiOU4uTiOjpI%2F5Ncx8jBhkzaOXZpQ7Hog4TRV4Dr1nuM666ut%2BjT71D2Ap%2FhFXTZUopDBngAe6ZzCdvGZU8%3D; WM_NIKE=9ca17ae2e6ffcda170e2e6eea2e55f81b6aea8f73cba928fa2d85e968a9baaaa548ceeaad6b76ab0bdab86cb2af0fea7c3b92ab2bf87d1d444f6b59cd4c16d9389b8d5f05d9194a286e167988987a5d94095bc969aca4991bd9dd6ee6b9a928b94ce419bb781b6b77f98b7818bf343edeb8284fb34aa9ea88cf96b8d889691d43d8cb1a9d5d75a96ec8c93b466b793fad7b57fb8f5a6b5b63b88ee8f91ae6486889cbbd865b49c8e8fe64ba7ea969bc270b69996b6bb37e2a3; WM_TID=1wcoN%2B7kI7BAREVQEVc6WV3NbdSF3HOg; MUSIC_U=e358cc9187d186b8a53adbbb1bb57faac13d5952a1c847e89e70eeddcb2de41333a649814e309366; __remember_me=true
//    User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 CloudMusic/0.1.1 NeteaseMusic/7.0.0

    @IBInspectable var source: String? {
        didSet {
            if isViewLoaded {
                src = source.flatMap {
                    return URL(string: $0)
                }
            }
        }
    }
    
    override func loadView() {
        super.loadView()
        
        webView = NMWebView(frame: view.bounds, configuration: Self.configuration).then {
            view.insertSubview($0, at: 0)
            $0.delegate = self
            $0.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                $0.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor),
                $0.leftAnchor.constraint(equalTo: view.leftAnchor),
                $0.rightAnchor.constraint(equalTo: view.rightAnchor),
                $0.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            ])
        }
        
        src = source.flatMap {
            return URL(string: $0)
        }
    }
    
    func webView(_ webView: NMWebView, titleDidChange title: String?) {
        self.title = title
    }
    
    static var configuration: WKWebViewConfiguration = .init()

    private var progressView: UIProgressView?
    private var webView: WKWebView?
    private var src: URL? {
        willSet {
            guard let webView = webView, newValue != src else {
                return
            }
            
            src.map { _ in
                webView.stopLoading()
            }
            
            newValue.map {
                _ = webView.load(.init(url: $0))
            }
        }
    }
}
